/*!
 * \file WtBtPorter.cpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 回测Porter接口实现
 * 
 * \details 本文件实现了WonderTrader回测系统的Porter接口，提供跨语言调用支持
 *          主要功能包括：
 *          - 回测系统初始化和配置
 *          - CTA/SEL/HFT三种策略类型的完整接口实现
 *          - 历史数据加载和外部数据源支持
 *          - 策略回调函数注册和事件处理
 *          - 回测执行控制和结果输出
 *          - 日志记录和版本信息管理
 *          - 缓存管理和资源清理
 */
#include "WtBtPorter.h"
#include "WtBtRunner.h"

#include "../WtBtCore/WtHelper.h"
#include "../WtBtCore/CtaMocker.h"
#include "../WtBtCore/SelMocker.h"
#include "../WtBtCore/HftMocker.h"

#include "../WTSTools/WTSLogger.h"

#include "../Includes/WTSVersion.h"


#ifdef _WIN32
#ifdef _WIN64
char PLATFORM_NAME[] = "X64";
#else
char PLATFORM_NAME[] = "X86";
#endif
#else
char PLATFORM_NAME[] = "UNIX";
#endif

/**
 * @brief 获取回测运行器实例
 * @details 获取全局唯一的回测运行器实例，采用单例模式
 * @return WtBtRunner& 回测运行器引用
 */
WtBtRunner& getRunner()
{
	static WtBtRunner runner;
	return runner;
}

/**
 * @brief 注册事件回调函数
 * @details 注册回测系统事件回调函数，用于接收系统事件通知
 * @param cbEvt 事件回调函数指针
 */
void register_evt_callback(FuncEventCallback cbEvt)
{
	getRunner().registerEvtCallback(cbEvt);
}

/**
 * @brief 注册CTA策略回调函数
 * @details 注册CTA策略的各种回调函数，包括初始化、tick、计算、K线、会话事件等
 * @param cbInit 策略初始化回调函数
 * @param cbTick tick数据回调函数
 * @param cbCalc 策略计算回调函数
 * @param cbBar K线数据回调函数
 * @param cbSessEvt 会话事件回调函数
 * @param cbCalcDone 计算完成回调函数（可选）
 */
void register_cta_callbacks(FuncStraInitCallback cbInit, FuncStraTickCallback cbTick, FuncStraCalcCallback cbCalc, 
	FuncStraBarCallback cbBar, FuncSessionEvtCallback cbSessEvt, FuncStraCalcCallback cbCalcDone/* = NULL*/)
{
	getRunner().registerCtaCallbacks(cbInit, cbTick, cbCalc, cbBar, cbSessEvt, cbCalcDone);
}

/**
 * @brief 注册SEL策略回调函数
 * @details 注册选股策略的各种回调函数，包括初始化、tick、计算、K线、会话事件等
 * @param cbInit 策略初始化回调函数
 * @param cbTick tick数据回调函数
 * @param cbCalc 策略计算回调函数
 * @param cbBar K线数据回调函数
 * @param cbSessEvt 会话事件回调函数
 * @param cbCalcDone 计算完成回调函数（可选）
 */
void register_sel_callbacks(FuncStraInitCallback cbInit, FuncStraTickCallback cbTick, FuncStraCalcCallback cbCalc, 
	FuncStraBarCallback cbBar, FuncSessionEvtCallback cbSessEvt, FuncStraCalcCallback cbCalcDone/* = NULL*/)
{
	getRunner().registerSelCallbacks(cbInit, cbTick, cbCalc, cbBar, cbSessEvt, cbCalcDone);
}

/**
 * @brief 注册HFT策略回调函数
 * @details 注册高频交易策略的各种回调函数，包括初始化、tick、K线、通道、订单、成交等
 * @param cbInit 策略初始化回调函数
 * @param cbTick tick数据回调函数
 * @param cbBar K线数据回调函数
 * @param cbChnl 通道事件回调函数
 * @param cbOrd 订单回调函数
 * @param cbTrd 成交回调函数
 * @param cbEntrust 委托回调函数
 * @param cbOrdDtl 订单明细回调函数
 * @param cbOrdQue 订单队列回调函数
 * @param cbTrans 逐笔成交回调函数
 * @param cbSessEvt 会话事件回调函数
 */
void register_hft_callbacks(FuncStraInitCallback cbInit, FuncStraTickCallback cbTick, FuncStraBarCallback cbBar,
	FuncHftChannelCallback cbChnl, FuncHftOrdCallback cbOrd, FuncHftTrdCallback cbTrd, FuncHftEntrustCallback cbEntrust,
	FuncStraOrdDtlCallback cbOrdDtl, FuncStraOrdQueCallback cbOrdQue, FuncStraTransCallback cbTrans, FuncSessionEvtCallback cbSessEvt)
{
	getRunner().registerHftCallbacks(cbInit, cbTick, cbBar, cbChnl, cbOrd, cbTrd, cbEntrust, cbOrdDtl, cbOrdQue, cbTrans, cbSessEvt);
}

/**
 * @brief 注册外部数据加载器
 * @details 注册外部数据加载器，支持自定义数据源加载K线、tick、复权因子等数据
 * @param fnlBarLoader 最终K线数据加载器
 * @param rawBarLoader 原始K线数据加载器
 * @param fctLoader 复权因子加载器
 * @param tickLoader tick数据加载器
 * @param bAutoTrans 是否自动转换数据格式
 */
void register_ext_data_loader(FuncLoadFnlBars fnlBarLoader, FuncLoadRawBars rawBarLoader, FuncLoadAdjFactors fctLoader, FuncLoadRawTicks tickLoader, bool bAutoTrans)
{
	getRunner().registerExtDataLoader(fnlBarLoader, rawBarLoader, fctLoader, tickLoader, bAutoTrans);
}

/**
 * @brief 推送原始K线数据
 * @details 向回测系统推送原始K线数据
 * @param bars K线数据数组指针
 * @param count K线数据条数
 */
void feed_raw_bars(WTSBarStruct* bars, WtUInt32 count)
{
	getRunner().feedRawBars(bars, count);
}

/**
 * @brief 推送原始tick数据
 * @details 向回测系统推送原始tick数据
 * @param ticks tick数据数组指针
 * @param count tick数据条数
 */
void feed_raw_ticks(WTSTickStruct* ticks, WtUInt32 count)
{
	getRunner().feedRawTicks(ticks, count);
}

/**
 * @brief 初始化回测系统
 * @details 初始化回测系统，设置日志配置和输出目录
 * @param logProfile 日志配置文件路径或内容
 * @param isFile 是否为文件路径（true）或配置内容（false）
 * @param outDir 输出目录路径
 */
void init_backtest(const char* logProfile, bool isFile, const char* outDir)
{
	static bool inited = false;

	if (inited)
		return;

	getRunner().init(logProfile, isFile, outDir);

	inited = true;
}

/**
 * @brief 配置回测系统
 * @details 配置回测系统参数，加载配置文件
 * @param cfgfile 配置文件路径或内容
 * @param isFile 是否为文件路径（true）或配置内容（false）
 */
void config_backtest(const char* cfgfile, bool isFile)
{
	static bool inited = false;

	if (inited)
		return;

	if (strlen(cfgfile) == 0)
		getRunner().config("configbt.json", true);
	else
		getRunner().config(cfgfile, isFile);
}

/**
 * @brief 设置回测时间范围
 * @details 设置回测的开始时间和结束时间
 * @param stime 开始时间（时间戳格式）
 * @param etime 结束时间（时间戳格式）
 */
void set_time_range(WtUInt64 stime, WtUInt64 etime)
{
	getRunner().set_time_range(stime, etime);
}

/**
 * @brief 启用tick级别回测
 * @details 启用或禁用tick级别的回测模式
 * @param bEnabled 是否启用tick级别回测
 */
void enable_tick(bool bEnabled /* = true */)
{
	getRunner().enable_tick(bEnabled);
}

/**
 * @brief 运行回测
 * @details 开始执行回测，可选择是否输出结果和异步执行
 * @param bNeedDump 是否需要输出回测结果
 * @param bAsync 是否异步执行
 */
void run_backtest(bool bNeedDump, bool bAsync)
{
	getRunner().run(bNeedDump, bAsync);
}

/**
 * @brief 停止回测
 * @details 停止正在运行的回测
 */
void stop_backtest()
{
	getRunner().stop();
}

/**
 * @brief 释放回测资源
 * @details 释放回测系统占用的所有资源
 */
void release_backtest()
{
	getRunner().release();
}

/**
 * @brief 获取版本信息
 * @details 获取WonderTrader回测系统的版本信息
 * @return const char* 版本信息字符串
 */
const char* get_version()
{
	static std::string _ver;
	if(_ver.empty())
	{
		_ver = PLATFORM_NAME;
		_ver += " ";
		_ver += WT_VERSION;
		_ver += " Build@";
		_ver += __DATE__;
		_ver += " ";
		_ver += __TIME__;
	}
	return _ver.c_str();
}

/**
 * @brief 清理缓存
 * @details 清理回测系统的所有缓存数据
 */
void clear_cache()
{
	getRunner().clear_cache();
}

/**
 * @brief 写入日志
 * @details 向指定分类写入日志信息
 * @param level 日志级别
 * @param message 日志消息
 * @param catName 日志分类名称
 */
void write_log(WtUInt32 level, const char* message, const char* catName)
{
	if (strlen(catName) > 0)
	{
		WTSLogger::log_raw_by_cat(catName, (WTSLogLevel)level, message);
	}
	else
	{
		WTSLogger::log_raw((WTSLogLevel)level, message);
	}
}

/**
 * @brief 初始化CTA策略模拟器
 * @details 创建并初始化CTA策略模拟器实例
 * @param name 策略名称
 * @param slippage 滑点设置（默认为0）
 * @param hook 是否启用钩子（默认为false）
 * @param persistData 是否持久化数据（默认为true）
 * @return CtxHandler 策略上下文句柄
 */
CtxHandler init_cta_mocker(const char* name, int slippage/* = 0*/, bool hook/* = false*/, bool persistData/* = true*/)
{
	return getRunner().initCtaMocker(name, slippage, hook, persistData);
}

/**
 * @brief 初始化HFT策略模拟器
 * @details 创建并初始化HFT策略模拟器实例
 * @param name 策略名称
 * @param hook 是否启用钩子（默认为false）
 * @return CtxHandler 策略上下文句柄
 */
CtxHandler init_hft_mocker(const char* name, bool hook/* = false*/)
{
	return getRunner().initHftMocker(name, hook);
}

/**
 * @brief 初始化SEL策略模拟器
 * @details 创建并初始化选股策略模拟器实例
 * @param name 策略名称
 * @param date 基准日期
 * @param time 基准时间
 * @param period 调仓周期
 * @param trdtpl 交易日模板（默认为"CHINA"）
 * @param session 交易时段（默认为"TRADING"）
 * @param slippage 滑点设置（默认为0）
 * @return CtxHandler 策略上下文句柄
 */
CtxHandler init_sel_mocker(const char* name, WtUInt32 date, WtUInt32 time, const char* period, const char* trdtpl/* = "CHINA"*/, const char* session/* = "TRADING"*/, int slippage/* = 0*/)
{
	return getRunner().initSelMocker(name, date, time, period, trdtpl, session, slippage);
}

/**
 * @brief 推送复权因子数据
 * @details 向回测系统推送指定合约的复权因子数据
 * @param stdCode 标准合约代码
 * @param dates 日期数组
 * @param factors 复权因子数组
 * @param count 数据条数
 */
void feed_adj_factors(WtString stdCode, WtUInt32* dates, double* factors, WtUInt32 count)
{
	getRunner().feedAdjFactors(stdCode, (uint32_t*)dates, factors, (uint32_t)count);
}

#pragma region "CTA策略回调函数"
/**
 * @brief CTA策略开多仓
 * @details CTA策略开多仓操作，支持限价和止损价设置
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 开仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_enter_long(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_enter_long(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略平多仓
 * @details CTA策略平多仓操作，支持限价和止损价设置
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 平仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_exit_long(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_exit_long(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略开空仓
 * @details CTA策略开空仓操作，支持限价和止损价设置
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 开仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_enter_short(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_enter_short(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略平空仓
 * @details CTA策略平空仓操作，支持限价和止损价设置
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 平仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_exit_short(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_exit_short(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略获取K线数据
 * @details CTA策略获取指定合约的K线数据，支持主力合约和普通合约
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param period K线周期
 * @param barCnt K线条数
 * @param isMain 是否为主力合约
 * @param cb K线数据回调函数
 * @return WtUInt32 实际获取的K线条数
 */
WtUInt32 cta_get_bars(CtxHandler cHandle, const char* stdCode, const char* period, WtUInt32 barCnt, bool isMain, FuncGetBarsCallback cb)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;
	try
	{
		WTSKlineSlice* kData = ctx->stra_get_bars(stdCode, period, barCnt, isMain);
		if (kData)
		{
			WtUInt32 reaCnt = kData->size();
			cb(cHandle, stdCode, period, kData->at(0), reaCnt, isMain);
			kData->release();
			return reaCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief CTA策略获取tick数据
 * @details CTA策略获取指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param tickCnt tick数据条数
 * @param cb tick数据回调函数
 * @return WtUInt32 实际获取的tick条数
 */
WtUInt32	cta_get_ticks(CtxHandler cHandle, const char* stdCode, WtUInt32 tickCnt, FuncGetTicksCallback cb)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;
	try
	{
		WTSTickSlice* tData = ctx->stra_get_ticks(stdCode, tickCnt);
		if (tData)
		{
			WtUInt32 reaCnt = tData->size();
			cb(cHandle, stdCode, (WTSTickStruct*)tData->at(0), reaCnt, true);
			tData->release();
			return reaCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief CTA策略获取持仓盈亏
 * @details CTA策略获取指定合约的持仓盈亏
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 持仓盈亏
 */
double cta_get_position_profit(CtxHandler cHandle, const char* stdCode)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position_profit(stdCode);
}

/**
 * @brief CTA策略获取明细开仓时间
 * @details CTA策略获取指定合约明细的开仓时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param openTag 开仓标签
 * @return WtUInt64 开仓时间
 */
WtUInt64 cta_get_detail_entertime(CtxHandler cHandle, const char* stdCode, const char* openTag)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_detail_entertime(stdCode, openTag);
}

/**
 * @brief CTA策略获取明细开仓成本
 * @details CTA策略获取指定合约明细的开仓成本
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param openTag 开仓标签
 * @return double 开仓成本
 */
double cta_get_detail_cost(CtxHandler cHandle, const char* stdCode, const char* openTag)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_detail_cost(stdCode, openTag);
}

/**
 * @brief CTA策略获取明细盈亏
 * @details CTA策略获取指定合约明细的盈亏情况
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param openTag 开仓标签
 * @param flag 盈亏标志（0-浮动盈亏，1-最大浮盈，2-最大浮亏）
 * @return double 明细盈亏
 */
double cta_get_detail_profit(CtxHandler cHandle, const char* stdCode, const char* openTag, int flag)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_detail_profit(stdCode, openTag, flag);
}

/**
 * @brief CTA策略获取持仓均价
 * @details CTA策略获取指定合约的持仓均价
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 持仓均价
 */
double cta_get_position_avgpx(CtxHandler cHandle, const char* stdCode)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position_avgpx(stdCode);
}

/**
 * @brief CTA策略获取所有持仓
 * @details CTA策略获取所有合约的持仓信息
 * @param cHandle 策略上下文句柄
 * @param cb 持仓信息回调函数
 */
void cta_get_all_position(CtxHandler cHandle, FuncGetPositionCallback cb)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
	{
		cb(cHandle, "", 0, true);
		return;
	}

	ctx->enum_position([cb, cHandle](const char* stdCode, double qty) {
		cb(cHandle, stdCode, qty, false);
	});

	cb(cHandle, "", 0, true);
}

/**
 * @brief CTA策略获取持仓
 * @details CTA策略获取指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param bOnlyValid 是否只获取有效持仓
 * @param openTag 开仓标签
 * @return double 持仓数量
 */
double cta_get_position(CtxHandler cHandle, const char* stdCode, bool bOnlyValid, const char* openTag)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position(stdCode, bOnlyValid, openTag);
}

/**
 * @brief CTA策略获取资金数据
 * @details CTA策略获取资金相关数据
 * @param cHandle 策略上下文句柄
 * @param flag 数据标志（0-动态权益，1-总平仓盈亏，2-总浮动盈亏，3-总手续费）
 * @return double 资金数据
 */
double cta_get_fund_data(CtxHandler cHandle, int flag)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_fund_data(flag);
}

/**
 * @brief CTA策略设置持仓
 * @details CTA策略设置指定合约的目标持仓
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 目标持仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_set_position(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_set_position(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略获取首次开仓时间
 * @details CTA策略获取指定合约的首次开仓时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return WtUInt64 首次开仓时间
 */
WtUInt64 cta_get_first_entertime(CtxHandler cHandle, const char* stdCode)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_first_entertime(stdCode);
}

/**
 * @brief CTA策略获取最后开仓时间
 * @details CTA策略获取指定合约的最后开仓时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return WtUInt64 最后开仓时间
 */
WtUInt64 cta_get_last_entertime(CtxHandler cHandle, const char* stdCode)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_last_entertime(stdCode);
}

/**
 * @brief CTA策略获取最后平仓时间
 * @details CTA策略获取指定合约的最后平仓时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return WtUInt64 最后平仓时间
 */
WtUInt64 cta_get_last_exittime(CtxHandler cHandle, const char* stdCode)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_last_exittime(stdCode);
}

/**
 * @brief CTA策略获取最后开仓价格
 * @details CTA策略获取指定合约的最后开仓价格
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 最后开仓价格
 */
double cta_get_last_enterprice(CtxHandler cHandle, const char* stdCode)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_last_enterprice(stdCode);
}

/**
 * @brief CTA策略获取合约价格
 * @details CTA策略获取指定合约的最新价格
 * @param stdCode 标准合约代码
 * @return double 最新价格
 */
double cta_get_price(const char* stdCode)
{
	return getRunner().replayer().get_cur_price(stdCode);
}

/**
 * @brief CTA策略获取交易日
 * @details CTA策略获取当前交易日
 * @return WtUInt32 交易日（YYYYMMDD格式）
 */
WtUInt32 cta_get_tdate()
{
	return getRunner().replayer().get_trading_date();
}

/**
 * @brief CTA策略获取当前日期
 * @details CTA策略获取当前日期
 * @return WtUInt32 当前日期（YYYYMMDD格式）
 */
WtUInt32 cta_get_date()
{
	return getRunner().replayer().get_date();
}

/**
 * @brief CTA策略获取当前时间
 * @details CTA策略获取当前时间
 * @return WtUInt32 当前时间（HHMM格式）
 */
WtUInt32 cta_get_time()
{
	return getRunner().replayer().get_min_time();
}

/**
 * @brief CTA策略记录日志
 * @details CTA策略记录自定义日志信息
 * @param cHandle 策略上下文句柄
 * @param message 日志消息
 */
void cta_log_text(CtxHandler cHandle, const char* message)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_log_info(message);
}

/**
 * @brief CTA策略保存用户数据
 * @details CTA策略保存用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param val 数据值
 */
void cta_save_userdata(CtxHandler cHandle, const char* key, const char* val)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_save_user_data(key, val);
}

/**
 * @brief CTA策略加载用户数据
 * @details CTA策略加载用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param defVal 默认值
 * @return WtString 数据值
 */
WtString cta_load_userdata(CtxHandler cHandle, const char* key, const char* defVal)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return defVal;

	return ctx->stra_load_user_data(key, defVal);
}

/**
 * @brief CTA策略订阅tick数据
 * @details CTA策略订阅指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void cta_sub_ticks(CtxHandler cHandle, const char* stdCode)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_sub_ticks(stdCode);
}

/**
 * @brief CTA策略单步执行
 * @details CTA策略执行单步计算，用于调试
 * @param cHandle 策略上下文句柄
 * @return bool 执行是否成功
 */
bool cta_step(CtxHandler cHandle)
{
	CtaMocker* ctx = getRunner().cta_mocker();
	if (ctx == NULL)
		return false;

	return ctx->step_calc();
}
#pragma endregion "CTA策略回调函数"

#pragma region "SEL策略回调函数"
/**
 * @brief SEL策略保存用户数据
 * @details SEL策略保存用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param val 数据值
 */
void sel_save_userdata(CtxHandler cHandle, const char* key, const char* val)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_save_user_data(key, val);
}

/**
 * @brief SEL策略加载用户数据
 * @details SEL策略加载用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param defVal 默认值
 * @return WtString 数据值
 */
WtString sel_load_userdata(CtxHandler cHandle, const char* key, const char* defVal)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return defVal;

	return ctx->stra_load_user_data(key, defVal);
}

/**
 * @brief SEL策略记录日志
 * @details SEL策略记录自定义日志信息
 * @param cHandle 策略上下文句柄
 * @param message 日志消息
 */
void sel_log_text(CtxHandler cHandle, const char* message)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_log_info(message);
}

/**
 * @brief SEL策略获取合约价格
 * @details SEL策略获取指定合约的最新价格
 * @param stdCode 标准合约代码
 * @return double 最新价格
 */
double sel_get_price(const char* stdCode)
{
	return getRunner().replayer().get_cur_price(stdCode);
}

/**
 * @brief SEL策略获取当前日期
 * @details SEL策略获取当前日期
 * @return WtUInt32 当前日期（YYYYMMDD格式）
 */
WtUInt32 sel_get_date()
{
	return getRunner().replayer().get_date();
}

/**
 * @brief SEL策略获取当前时间
 * @details SEL策略获取当前时间
 * @return WtUInt32 当前时间（HHMM格式）
 */
WtUInt32 sel_get_time()
{
	return getRunner().replayer().get_min_time();
}

/**
 * @brief SEL策略获取所有持仓
 * @details SEL策略获取所有合约的持仓信息
 * @param cHandle 策略上下文句柄
 * @param cb 持仓信息回调函数
 */
void sel_get_all_position(CtxHandler cHandle, FuncGetPositionCallback cb)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
	{
		cb(cHandle, "", 0, true);
		return;
	}

	ctx->enum_position([cb, cHandle](const char* stdCode, double qty) {
		cb(cHandle, stdCode, qty, false);
	});

	cb(cHandle, "", 0, true);
}

/**
 * @brief SEL策略获取持仓
 * @details SEL策略获取指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param bOnlyValid 是否只获取有效持仓
 * @param openTag 开仓标签
 * @return double 持仓数量
 */
double sel_get_position(CtxHandler cHandle, const char* stdCode, bool bOnlyValid, const char* openTag)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position(stdCode, bOnlyValid, openTag);
}

/**
 * @brief SEL策略获取K线数据
 * @details SEL策略获取指定合约的K线数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param period K线周期
 * @param barCnt K线条数
 * @param cb K线数据回调函数
 * @return WtUInt32 实际获取的K线条数
 */
WtUInt32 sel_get_bars(CtxHandler cHandle, const char* stdCode, const char* period, WtUInt32 barCnt, FuncGetBarsCallback cb)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return 0;
	try
	{
		WTSKlineSlice* kData = ctx->stra_get_bars(stdCode, period, barCnt);
		if (kData)
		{
			WtUInt32 reaCnt = (WtUInt32)kData->size();

			for (uint32_t i = 0; i < kData->get_block_counts(); i++)
				cb(cHandle, stdCode, period, kData->get_block_addr(i), kData->get_block_size(i), i == kData->get_block_counts() - 1);

			kData->release();
			return reaCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief SEL策略设置持仓
 * @details SEL策略设置指定合约的目标持仓
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 目标持仓数量
 * @param userTag 用户标签
 */
void sel_set_position(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return;

	//多因子引擎，限价为0
	ctx->stra_set_position(stdCode, qty, userTag);
}

/**
 * @brief SEL策略获取tick数据
 * @details SEL策略获取指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param tickCnt tick数据条数
 * @param cb tick数据回调函数
 * @return WtUInt32 实际获取的tick条数
 */
WtUInt32	sel_get_ticks(CtxHandler cHandle, const char* stdCode, WtUInt32 tickCnt, FuncGetTicksCallback cb)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return 0;
	try
	{
		WTSTickSlice* tData = ctx->stra_get_ticks(stdCode, tickCnt);
		if (tData)
		{
			uint32_t thisCnt = min(tickCnt, (WtUInt32)tData->size());
			cb(cHandle, stdCode, (WTSTickStruct*)tData->at(0), thisCnt, true);
			tData->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief SEL策略订阅tick数据
 * @details SEL策略订阅指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void sel_sub_ticks(CtxHandler cHandle, const char* stdCode)
{
	SelMocker* ctx = getRunner().sel_mocker();
	if (ctx == NULL)
		return;

	ctx->stra_sub_ticks(stdCode);
}
#pragma endregion "SEL策略回调函数"

#pragma region "HFT策略回调函数"
/**
 * @brief HFT策略获取持仓
 * @details HFT策略获取指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param bOnlyValid 是否只获取有效持仓
 * @return double 持仓数量
 */
double hft_get_position(CtxHandler cHandle, const char* stdCode, bool bOnlyValid)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	return mocker->stra_get_position(stdCode, bOnlyValid);
}

/**
 * @brief HFT策略获取持仓盈亏
 * @details HFT策略获取指定合约的持仓盈亏
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 持仓盈亏
 */
double hft_get_position_profit(CtxHandler cHandle, const char* stdCode)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	return mocker->stra_get_position_profit(stdCode);
}

/**
 * @brief HFT策略获取未完成交易
 * @details HFT策略获取指定合约的未完成交易数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 未完成交易数量
 */
double hft_get_undone(CtxHandler cHandle, const char* stdCode)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	return mocker->stra_get_undone(stdCode);
}

/**
 * @brief HFT策略获取合约价格
 * @details HFT策略获取指定合约的最新价格
 * @param stdCode 标准合约代码
 * @return double 最新价格
 */
double hft_get_price(const char* stdCode)
{
	return getRunner().replayer().get_cur_price(stdCode);
}

/**
 * @brief HFT策略获取当前日期
 * @details HFT策略获取当前日期
 * @return WtUInt32 当前日期（YYYYMMDD格式）
 */
WtUInt32 hft_get_date()
{
	return getRunner().replayer().get_date();
}

/**
 * @brief HFT策略获取当前时间
 * @details HFT策略获取当前时间
 * @return WtUInt32 当前时间（HHMM格式）
 */
WtUInt32 hft_get_time()
{
	return getRunner().replayer().get_raw_time();
}

/**
 * @brief HFT策略获取秒数
 * @details HFT策略获取当前秒数
 * @return WtUInt32 秒数
 */
WtUInt32 hft_get_secs()
{
	return getRunner().replayer().get_secs();
}

/**
 * @brief HFT策略获取K线数据
 * @details HFT策略获取指定合约的K线数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param period K线周期
 * @param barCnt K线条数
 * @param cb K线数据回调函数
 * @return WtUInt32 实际获取的K线条数
 */
WtUInt32 hft_get_bars(CtxHandler cHandle, const char* stdCode, const char* period, WtUInt32 barCnt, FuncGetBarsCallback cb)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	try
	{
		WTSKlineSlice* kData = mocker->stra_get_bars(stdCode, period, barCnt);
		if (kData)
		{
			WtUInt32 reaCnt = kData->size();
			cb(cHandle, stdCode, period, kData->at(0), reaCnt, true);
			kData->release();
			return reaCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取tick数据
 * @details HFT策略获取指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param tickCnt tick数据条数
 * @param cb tick数据回调函数
 * @return WtUInt32 实际获取的tick条数
 */
WtUInt32 hft_get_ticks(CtxHandler cHandle, const char* stdCode, WtUInt32 tickCnt, FuncGetTicksCallback cb)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	try
	{
		WTSTickSlice* tData = mocker->stra_get_ticks(stdCode, tickCnt);
		if (tData)
		{
			uint32_t thisCnt = min(tickCnt, (WtUInt32)tData->size());
			cb(cHandle, stdCode, (WTSTickStruct*)tData->at(0), thisCnt, true);
			tData->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取订单队列
 * @details HFT策略获取指定合约的订单队列数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param itemCnt 数据条数
 * @param cb 订单队列回调函数
 * @return WtUInt32 实际获取的数据条数
 */
WtUInt32 hft_get_ordque(CtxHandler cHandle, const char* stdCode, WtUInt32 itemCnt, FuncGetOrdQueCallback cb)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	try
	{
		WTSOrdQueSlice* dataSlice = mocker->stra_get_order_queue(stdCode, itemCnt);
		if (dataSlice)
		{
			uint32_t thisCnt = min(itemCnt, (WtUInt32)dataSlice->size());
			cb(cHandle, stdCode, (WTSOrdQueStruct*)dataSlice->at(0), thisCnt, true);
			dataSlice->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取订单明细
 * @details HFT策略获取指定合约的订单明细数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param itemCnt 数据条数
 * @param cb 订单明细回调函数
 * @return WtUInt32 实际获取的数据条数
 */
WtUInt32 hft_get_orddtl(CtxHandler cHandle, const char* stdCode, WtUInt32 itemCnt, FuncGetOrdDtlCallback cb)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	try
	{
		WTSOrdDtlSlice* dataSlice = mocker->stra_get_order_detail(stdCode, itemCnt);
		if (dataSlice)
		{
			uint32_t thisCnt = min(itemCnt, (WtUInt32)dataSlice->size());
			cb(cHandle, stdCode, (WTSOrdDtlStruct*)dataSlice->at(0), thisCnt, true);
			dataSlice->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取逐笔成交
 * @details HFT策略获取指定合约的逐笔成交数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param itemCnt 数据条数
 * @param cb 逐笔成交回调函数
 * @return WtUInt32 实际获取的数据条数
 */
WtUInt32 hft_get_trans(CtxHandler cHandle, const char* stdCode, WtUInt32 itemCnt, FuncGetTransCallback cb)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return 0;

	try
	{
		WTSTransSlice* dataSlice = mocker->stra_get_transaction(stdCode, itemCnt);
		if (dataSlice)
		{
			uint32_t thisCnt = min(itemCnt, (WtUInt32)dataSlice->size());
			cb(cHandle, stdCode, (WTSTransStruct*)dataSlice->at(0), thisCnt, true);
			dataSlice->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略记录日志
 * @details HFT策略记录自定义日志信息
 * @param cHandle 策略上下文句柄
 * @param message 日志消息
 */
void hft_log_text(CtxHandler cHandle, const char* message)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return;

	mocker->stra_log_info(message);
}

/**
 * @brief HFT策略订阅tick数据
 * @details HFT策略订阅指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_ticks(CtxHandler cHandle, const char* stdCode)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return;

	mocker->stra_sub_ticks(stdCode);
}

/**
 * @brief HFT策略订阅订单明细
 * @details HFT策略订阅指定合约的订单明细数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_order_detail(CtxHandler cHandle, const char* stdCode)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return;

	mocker->stra_sub_order_details(stdCode);
}

/**
 * @brief HFT策略订阅订单队列
 * @details HFT策略订阅指定合约的订单队列数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_order_queue(CtxHandler cHandle, const char* stdCode)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return;

	mocker->stra_sub_order_queues(stdCode);
}

/**
 * @brief HFT策略订阅逐笔成交
 * @details HFT策略订阅指定合约的逐笔成交数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_transaction(CtxHandler cHandle, const char* stdCode)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return;

	mocker->stra_sub_transactions(stdCode);
}

/**
 * @brief HFT策略取消交易
 * @details HFT策略取消指定的交易订单
 * @param cHandle 策略上下文句柄
 * @param localid 本地订单ID
 * @return bool 取消是否成功
 */
bool hft_cancel(CtxHandler cHandle, WtUInt32 localid)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return false;

	return mocker->stra_cancel(localid);
}

/**
 * @brief HFT策略取消所有交易
 * @details HFT策略取消指定合约的所有交易订单
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param isBuy 是否为买单
 * @return WtString 取消的订单ID列表
 */
WtString hft_cancel_all(CtxHandler cHandle, const char* stdCode, bool isBuy)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return "";

	std::stringstream ss;
	OrderIDs ids = mocker->stra_cancel(stdCode, isBuy, DBL_MAX);
	for (WtUInt32 localid : ids)
	{
		ss << localid << ",";
	}
	std::string ret = ss.str();
	ret = ret.substr(0, ret.size() - 1);
	return ret.c_str();
}

/**
 * @brief HFT策略买入交易
 * @details HFT策略执行买入交易
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param price 价格
 * @param qty 数量
 * @param userTag 用户标签
 * @param flag 交易标志
 * @return WtString 订单ID列表
 */
WtString hft_buy(CtxHandler cHandle, const char* stdCode, double price, double qty, const char* userTag, int flag)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return "";

	std::stringstream ss;
	OrderIDs ids = mocker->stra_buy(stdCode, price, qty, userTag, flag);
	for (WtUInt32 localid : ids)
	{
		ss << localid << ",";
	}
	std::string ret = ss.str();
	ret = ret.substr(0, ret.size() - 1);
	return ret.c_str();
}

/**
 * @brief HFT策略卖出交易
 * @details HFT策略执行卖出交易
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param price 价格
 * @param qty 数量
 * @param userTag 用户标签
 * @param flag 交易标志
 * @return WtString 订单ID列表
 */
WtString hft_sell(CtxHandler cHandle, const char* stdCode, double price, double qty, const char* userTag, int flag)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return "";

	std::stringstream ss;
	OrderIDs ids = mocker->stra_sell(stdCode, price, qty, userTag, flag);
	for (WtUInt32 localid : ids)
	{
		ss << localid << ",";
	}
	std::string ret = ss.str();
	ret = ret.substr(0, ret.size() - 1);
	return ret.c_str();
}

/**
 * @brief HFT策略保存用户数据
 * @details HFT策略保存用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param val 数据值
 */
void hft_save_userdata(CtxHandler cHandle, const char* key, const char* val)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return;

	mocker->stra_save_user_data(key, val);
}

/**
 * @brief HFT策略加载用户数据
 * @details HFT策略加载用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param defVal 默认值
 * @return WtString 数据值
 */
WtString hft_load_userdata(CtxHandler cHandle, const char* key, const char* defVal)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return defVal;

	return mocker->stra_load_user_data(key, defVal);
}

/**
 * @brief HFT策略单步执行
 * @details HFT策略执行单步操作，用于调试
 * @param cHandle 策略上下文句柄
 */
void hft_step(CtxHandler cHandle)
{
	HftMocker* mocker = getRunner().hft_mocker();
	if (mocker == NULL)
		return;

	mocker->step_tick();
}
#pragma endregion "HFT策略回调函数"